﻿namespace com.stifel.ProjectMgmt
{
    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Web.Caching;
    using System.Web.Script.Serialization;
    using System.Web.UI.WebControls;

    using com.stifel.Extensions.AssemblyExtensions;
    using com.stifel.Extensions.StringExtensions;
    using com.stifel.ProjectMgmtDao;

    using Microsoft.SharePoint;

    public partial class ProjectMgmtUserControl
    {
        #region Fields

        string _sitecollectionurl;
        string _UrlReferrer;

        #endregion Fields

        #region Properties

        string sitecollectionurl
        {
            get
            {
                if ( string.IsNullOrEmpty( _sitecollectionurl ) )
                    _sitecollectionurl = SPContext.Current.Web.Url;
                return _sitecollectionurl;
            }
        }

        string UrlReferrer
        {
            get
            {
                if ( string.IsNullOrEmpty( _UrlReferrer ) )
                    _UrlReferrer = ( string ) Page.Cache.Get( CacheKey.UrlReferrer );
                if ( string.IsNullOrEmpty( _UrlReferrer ) )
                    setUrlReferrer( );
                return _UrlReferrer;
            }
            set
            {
                _UrlReferrer = value;
                addToCache( CacheKey.UrlReferrer, value );
            }
        }

        #endregion Properties

        #region Methods

        void addToCache( string key, object value )
        {
            if ( value == null )
                Cache.Remove( key );
            else
                // cache for 10 hours
                Cache.Insert( key, value, null,
                    Cache.NoAbsoluteExpiration,
                    new TimeSpan( 10, 0, 0 ),
                    CacheItemPriority.Normal,
                    new CacheItemRemovedCallback(
                        delegate( string k, object v, CacheItemRemovedReason reason )
                        {
                        } ) );
        }

        List<jsonListBoxItem> deserializeJsonListBoxItems( string value )
        {
            JavaScriptSerializer j = new JavaScriptSerializer( );
            return j.Deserialize<List<jsonListBoxItem>>( value );
        }

        void flushcache( )
        {
            foreach ( string k in CacheKey.Values )
                Cache.Remove( k );
        }

        string getItemValue( string projectDetails, string siteUrl, string listTitle, Guid itemId )
        {
            ProjectId projectId = new ProjectId
            {
                ItemId = itemId,
                ListTitle = listTitle,
                SiteUrl = siteUrl
            };
            string pid = projectId.Value;

            return string.Format( "{0}||{1}", projectDetails, pid );
        }

        string getProjectDetailFormat( )
        {
            return Assembly.GetExecutingAssembly( ).GetManifestResourceAsString( string.Format( "{0}.scripts.projectdetail.htm", SharePointProjectItemName ) ).TrimNewLine( );
        }

        string getProjectDetails( StifelProject project )
        {
            // constants defined within project details format
            string PROJECTNAME = "$projectname$";
            string TEAMNAME = "$teamname$";
            string TEAMLEAD = "$teamlead$";
            string PROJECTSTATUS = "$projectstatus$";
            string DATEDUE = "$datedue$";
            string DATESTARTED = "$datestarted$";
            string PROJECTDESCRIPTION = "$projectdescription$";

            string s = getProjectDetailFormat( )
                .Replace( DATEDUE, project.GetDueDateAsString( ) )
                .Replace( DATESTARTED, project.GetStartDateAsString( ) )
                .Replace( PROJECTDESCRIPTION, project.ProjectDescription.StripHTML( ).TrimNewLine( ) )
                .Replace( PROJECTNAME, project.Name )
                .Replace( PROJECTSTATUS, project.GetProjectStatusAsString( ) )
                .Replace( TEAMLEAD, project.GetTeamsLeadAsString( ) )
                .Replace( TEAMNAME, project.GetTeamNameAsString( ) )
                .ToBase64String( );

            return s;
        }

        List<ListItem> getProjectsAsListItems( List<StifelProject> projects )
        {
            List<ListItem> list = new List<ListItem>( );
            foreach ( StifelProject project in projects )
            {
                list.Add( new ListItem
                {
                    Text = project.Name,
                    Value = getItemValue( getProjectDetails( project ), project.ParentSite.SiteUrl, project.ParentSite.ListTitle, project.UniqueId )
                } );
            }
            return list;
        }

        void loadActiveProjects( List<ProjectSite> sites )
        {
            List<StifelProject> projects = new List<StifelProject>( );
            StifelProjectDao dao = new StifelProjectDao( );
            projects = dao.GetActiveProjects( sites );
            uiActiveProjects.Items.AddRange( getProjectsAsListItems( projects ).ToArray( ) );
            uiActiveProjects.SelectedIndex = 0;
        }

        void loadInactiveProjects( List<ProjectSite> sites )
        {
            List<StifelProject> projects = new List<StifelProject>( );
            StifelProjectDao dao = new StifelProjectDao( );
            projects = dao.GetInactiveProjects( sites );
            uiInactiveProjects.Items.AddRange( getProjectsAsListItems( projects ).ToArray( ) );
            uiInactiveProjects.SelectedIndex = 0;
        }

        void loadNewProjects( List<ProjectSite> sites )
        {
            List<StifelProject> projects = new List<StifelProject>( );
            StifelProjectDao dao = new StifelProjectDao( );
            projects = dao.GetNewProjects( sites );
            uiNewProjects.Items.AddRange( getProjectsAsListItems( projects ).ToArray( ) );
            uiNewProjects.SelectedIndex = 0;
        }

        void loadProjects( )
        {
            uiSiteCollectionURL.Value = sitecollectionurl.UrlEncode( );
            uiExportButton.NavigateUrl = string.Format( "~/_layouts/com.stifel.ProjectMgmt/ExportProjectsToExcel.ashx?q={0}", sitecollectionurl.UrlEncode( ) );
            List<ProjectSite> sites = new List<ProjectSite>( );
            StifelProjectDao dao = new StifelProjectDao( );
            sites = dao.GetSitesWithProjectsDefined( sitecollectionurl );

            loadActiveProjects( sites );
            loadNewProjects( sites );
            loadInactiveProjects( sites );
            uiNumberOfSites.Text = string.Format( "<span class=\"miscinfo\">Projects found in {0} site{1}.</span>", sites.Count, sites.Count == 1 ? string.Empty : "s" );

            uiExportButton.Visible = sites.Count > 0;
        }

        void setUrlReferrer( )
        {
            if ( Request != null && Request.UrlReferrer != null )
                UrlReferrer = Request.UrlReferrer.ToString( );
            else if ( Request != null )
                UrlReferrer = Request.Url.ToString( );
        }

        void updateProjectRanking( )
        {
            /**
             * Created a charector array <delimiter> which we use for splitting the base64 string.
             * Obtained Json array from the hidden fields and saved them as strings in <acitveProjectsJsonArry>,<inactiveProjectsJsonArray>.
             * Deserilised them to <jsonListBoxItem> objects and sved them to two lists <activeProjectsCovertedJsonArray>,<inactiveProjectsCovertedJsonArray>.
             * Obtained the value part from each item in the list converted that to string (which is still a base 64 string) added to a list of strings <values>.
             * Took each string from the <values> list splited that into two using the delimitor created before.
             * Saved that to a string array <splitStrings>.
             * Now <splitString[1]> always contains the xml base 64 string.
             * Converted that xml base 64 to normal xml string
             * And then deserialised the xml and obtained <ProjectId> instances and saved them to the list <projectIdsForChangedOrder>
            **/
            char[ ] delimiter = new char[ ] { '|', '|' };
            List<ProjectId> activeProjectIdsForChangedOrder = new List<ProjectId>( );
            List<ProjectId> inActiveProjectIdsForChangedOrder = new List<ProjectId>( );

            //Obtained Json array from the hidden fields and saved them as strings in <acitveProjectsJsonArry>,<inactiveProjectsJsonArray>.

            string activeProjectsJsonArray = uiActiveProject_Items.Value;
            string inactiveProjectsJsonArray = uiInactiveProject_Items.Value;

            //Deserialized them to <jsonListBoxItem> objects and saved them to two lists <activeProjectsConvertedJsonArray>,<inactiveProjectsConvertedJsonArray>.

            List<jsonListBoxItem> activeProjectsConvertedJsonArray = deserializeJsonListBoxItems( activeProjectsJsonArray );
            List<jsonListBoxItem> inactiveProjectsConvertedJsonArray = deserializeJsonListBoxItems( inactiveProjectsJsonArray );

            //Obtained the value part from each item in the list converted that to string (which is still a base 64 string) added to a list of strings <values>.

            foreach ( jsonListBoxItem j in activeProjectsConvertedJsonArray )
            {
                /**
                 * Obtained the value from the json object.
                 * Converted that to string using <ToString>.
                 * Split using the delimiter.
                 * Copied that to <splitStrings> array.
                **/

                string[ ] splitStrings = ( j.value.ToString( ) ).Split( delimiter, StringSplitOptions.RemoveEmptyEntries );

                //deserialised the xml and obtained <ProjectId> instances and saved them to the list <activeProjectIdsForChangedOrder>

                activeProjectIdsForChangedOrder.Add( StringExtensions.DeserializeFromXml<ProjectId>( StringExtensions.FromBase64String( splitStrings[ 1 ] ) ) );
            }
            foreach ( jsonListBoxItem j in inactiveProjectsConvertedJsonArray )
            {

                /**
                 * Obtained the value from the json object.
                 * Converted that to string using <ToString>.
                 * Split using the delimiter.
                 * Copied that to <splitStrings> array.
                **/

                string[ ] splitStrings = ( j.value.ToString( ) ).Split( delimiter, StringSplitOptions.RemoveEmptyEntries );

                //deserialised the xml and obtained <ProjectId> instances and saved them to the list <inActiveProjectIdsForChangedOrder>

                inActiveProjectIdsForChangedOrder.Add( StringExtensions.DeserializeFromXml<ProjectId>( StringExtensions.FromBase64String( splitStrings[ 1 ] ) ) );
            }

            StifelProjectDao dao = new StifelProjectDao( );
            dao.UpdateProjectsRanking( activeProjectIdsForChangedOrder, inActiveProjectIdsForChangedOrder );
        }

        #endregion Methods
    }
}